//#region Header
///**
// * JsonData.cs
// *   Generic type to hold JSON data (objects, arrays, and so on). This is
// *   the default type returned by JsonMapper.ToObject().
// *
// * The authors disclaim copyright to this source code. For more details, see
// * the COPYING file included with this distribution.
// **/
//#endregion


//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Collections.Specialized;
//using System.IO;


//namespace LitJson
//{
//    public class JsonData : IJsonWrapper, IEquatable<JsonData>
//    {
//        #region Fields
//        private IList<JsonData>               inst_array;
//        private bool                          inst_boolean;
//        private double                        inst_double;
//        private int                           inst_int;
//        private long                          inst_long;
//        private IDictionary<string, JsonData> inst_object;
//        private string                        inst_string;
//        private string                        json;
//        private JsonType                      type;

//        // Used to implement the IOrderedDictionary interface
//        private IList<KeyValuePair<string, JsonData>> object_list;
//        #endregion


//        #region Properties
//        public int Count {
//            get { return EnsureCollection ().Count; }
//        }

//        public bool IsArray {
//            get { return type == JsonType.Array; }
//        }

//        public bool IsBoolean {
//            get { return type == JsonType.Boolean; }
//        }

//        public bool IsDouble {
//            get { return type == JsonType.Double; }
//        }

//        public bool IsInt {
//            get { return type == JsonType.Int; }
//        }

//        public bool IsLong {
//            get { return type == JsonType.Long; }
//        }

//        public bool IsObject {
//            get { return type == JsonType.Object; }
//        }

//        public bool IsString {
//            get { return type == JsonType.String; }
//        }

//        public ICollection<string> Keys {
//            get { EnsureDictionary (); return inst_object.Keys; }
//        }
//        #endregion


//        #region ICollection Properties
//        int ICollection.Count {
//            get {
//                return Count;
//            }
//        }

//        bool ICollection.IsSynchronized {
//            get {
//                return EnsureCollection ().IsSynchronized;
//            }
//        }

//        object ICollection.SyncRoot {
//            get {
//                return EnsureCollection ().SyncRoot;
//            }
//        }
//        #endregion


//        #region IDictionary Properties
//        bool IDictionary.IsFixedSize {
//            get {
//                return EnsureDictionary ().IsFixedSize;
//            }
//        }

//        bool IDictionary.IsReadOnly {
//            get {
//                return EnsureDictionary ().IsReadOnly;
//            }
//        }

//        ICollection IDictionary.Keys {
//            get {
//                EnsureDictionary ();
//                IList<string> keys = new List<string> ();

//                foreach (KeyValuePair<string, JsonData> entry in
//                         object_list) {
//                    keys.Add (entry.Key);
//                }

//                return (ICollection) keys;
//            }
//        }

//        ICollection IDictionary.Values {
//            get {
//                EnsureDictionary ();
//                IList<JsonData> values = new List<JsonData> ();

//                foreach (KeyValuePair<string, JsonData> entry in
//                         object_list) {
//                    values.Add (entry.Value);
//                }

//                return (ICollection) values;
//            }
//        }
//        #endregion



//        #region IJsonWrapper Properties
//        bool IJsonWrapper.IsArray {
//            get { return IsArray; }
//        }

//        bool IJsonWrapper.IsBoolean {
//            get { return IsBoolean; }
//        }

//        bool IJsonWrapper.IsDouble {
//            get { return IsDouble; }
//        }

//        bool IJsonWrapper.IsInt {
//            get { return IsInt; }
//        }

//        bool IJsonWrapper.IsLong {
//            get { return IsLong; }
//        }

//        bool IJsonWrapper.IsObject {
//            get { return IsObject; }
//        }

//        bool IJsonWrapper.IsString {
//            get { return IsString; }
//        }
//        #endregion


//        #region IList Properties
//        bool IList.IsFixedSize {
//            get {
//                return EnsureList ().IsFixedSize;
//            }
//        }

//        bool IList.IsReadOnly {
//            get {
//                return EnsureList ().IsReadOnly;
//            }
//        }
//        #endregion


//        #region IDictionary Indexer
//        object IDictionary.this[object key] {
//            get {
//                return EnsureDictionary ()[key];
//            }

//            set {
//                if (! (key is String))
//                    throw new ArgumentException (
//                        "The key has to be a string");

//                JsonData data = ToJsonData (value);

//                this[(string) key] = data;
//            }
//        }
//        #endregion


//        #region IOrderedDictionary Indexer
//        object IOrderedDictionary.this[int idx] {
//            get {
//                EnsureDictionary ();
//                return object_list[idx].Value;
//            }

//            set {
//                EnsureDictionary ();
//                JsonData data = ToJsonData (value);

//                KeyValuePair<string, JsonData> old_entry = object_list[idx];

//                inst_object[old_entry.Key] = data;

//                KeyValuePair<string, JsonData> entry =
//                    new KeyValuePair<string, JsonData> (old_entry.Key, data);

//                object_list[idx] = entry;
//            }
//        }
//        #endregion


//        #region IList Indexer
//        object IList.this[int index] {
//            get {
//                return EnsureList ()[index];
//            }

//            set {
//                EnsureList ();
//                JsonData data = ToJsonData (value);

//                this[index] = data;
//            }
//        }
//        #endregion


//        #region Public Indexers
//        public JsonData this[string prop_name] {
//            get {
//                EnsureDictionary ();
//                return inst_object[prop_name];
//            }

//            set {
//                EnsureDictionary ();

//                KeyValuePair<string, JsonData> entry =
//                    new KeyValuePair<string, JsonData> (prop_name, value);

//                if (inst_object.ContainsKey (prop_name)) {
//                    for (int i = 0; i < object_list.Count; i++) {
//                        if (object_list[i].Key == prop_name) {
//                            object_list[i] = entry;
//                            break;
//                        }
//                    }
//                } else
//                    object_list.Add (entry);

//                inst_object[prop_name] = value;

//                json = null;
//            }
//        }

//        public JsonData this[int index] {
//            get {
//                EnsureCollection ();

//                if (type == JsonType.Array)
//                    return inst_array[index];

//                return object_list[index].Value;
//            }

//            set {
//                EnsureCollection ();

//                if (type == JsonType.Array)
//                    inst_array[index] = value;
//                else {
//                    KeyValuePair<string, JsonData> entry = object_list[index];
//                    KeyValuePair<string, JsonData> new_entry =
//                        new KeyValuePair<string, JsonData> (entry.Key, value);

//                    object_list[index] = new_entry;
//                    inst_object[entry.Key] = value;
//                }

//                json = null;
//            }
//        }
//        #endregion


//        #region Constructors
//        public JsonData ()
//        {
//        }

//        public JsonData (bool boolean)
//        {
//            type = JsonType.Boolean;
//            inst_boolean = boolean;
//        }

//        public JsonData (double number)
//        {
//            type = JsonType.Double;
//            inst_double = number;
//        }

//        public JsonData (int number)
//        {
//            type = JsonType.Int;
//            inst_int = number;
//        }

//        public JsonData (long number)
//        {
//            type = JsonType.Long;
//            inst_long = number;
//        }

//        public JsonData (object obj)
//        {
//            if (obj is Boolean) {
//                type = JsonType.Boolean;
//                inst_boolean = (bool) obj;
//                return;
//            }

//            if (obj is Double) {
//                type = JsonType.Double;
//                inst_double = (double) obj;
//                return;
//            }

//            if (obj is Int32) {
//                type = JsonType.Int;
//                inst_int = (int) obj;
//                return;
//            }

//            if (obj is Int64) {
//                type = JsonType.Long;
//                inst_long = (long) obj;
//                return;
//            }

//            if (obj is String) {
//                type = JsonType.String;
//                inst_string = (string) obj;
//                return;
//            }

//            throw new ArgumentException (
//                "Unable to wrap the given object with JsonData");
//        }

//        public JsonData (string str)
//        {
//            type = JsonType.String;
//            inst_string = str;
//        }
//        #endregion


//        #region Implicit Conversions
//        public static implicit operator JsonData (Boolean data)
//        {
//            return new JsonData (data);
//        }

//        public static implicit operator JsonData (Double data)
//        {
//            return new JsonData (data);
//        }

//        public static implicit operator JsonData (Int32 data)
//        {
//            return new JsonData (data);
//        }

//        public static implicit operator JsonData (Int64 data)
//        {
//            return new JsonData (data);
//        }

//        public static implicit operator JsonData (String data)
//        {
//            return new JsonData (data);
//        }
//        #endregion


//        #region Explicit Conversions
//        public static explicit operator Boolean (JsonData data)
//        {
//            if (data.type != JsonType.Boolean)
//                throw new InvalidCastException (
//                    "Instance of JsonData doesn't hold a double");

//            return data.inst_boolean;
//        }

//        public static explicit operator Double (JsonData data)
//        {
//            if (data.type != JsonType.Double)
//                throw new InvalidCastException (
//                    "Instance of JsonData doesn't hold a double");

//            return data.inst_double;
//        }

//        public static explicit operator Int32 (JsonData data)
//        {
//            if (data.type != JsonType.Int)
//                throw new InvalidCastException (
//                    "Instance of JsonData doesn't hold an int");

//            return data.inst_int;
//        }

//        public static explicit operator Int64 (JsonData data)
//        {
//            if (data.type != JsonType.Long)
//                throw new InvalidCastException (
//                    "Instance of JsonData doesn't hold an int");

//            return data.inst_long;
//        }

//        public static explicit operator String (JsonData data)
//        {
//            if (data.type != JsonType.String)
//                throw new InvalidCastException (
//                    "Instance of JsonData doesn't hold a string");

//            return data.inst_string;
//        }
//        #endregion


//        #region ICollection Methods
//        void ICollection.CopyTo (Array array, int index)
//        {
//            EnsureCollection ().CopyTo (array, index);
//        }
//        #endregion


//        #region IDictionary Methods
//        void IDictionary.Add (object key, object value)
//        {
//            JsonData data = ToJsonData (value);

//            EnsureDictionary ().Add (key, data);

//            KeyValuePair<string, JsonData> entry =
//                new KeyValuePair<string, JsonData> ((string) key, data);
//            object_list.Add (entry);

//            json = null;
//        }

//        void IDictionary.Clear ()
//        {
//            EnsureDictionary ().Clear ();
//            object_list.Clear ();
//            json = null;
//        }

//        bool IDictionary.Contains (object key)
//        {
//            return EnsureDictionary ().Contains (key);
//        }

//        IDictionaryEnumerator IDictionary.GetEnumerator ()
//        {
//            return ((IOrderedDictionary) this).GetEnumerator ();
//        }

//        void IDictionary.Remove (object key)
//        {
//            EnsureDictionary ().Remove (key);

//            for (int i = 0; i < object_list.Count; i++) {
//                if (object_list[i].Key == (string) key) {
//                    object_list.RemoveAt (i);
//                    break;
//                }
//            }

//            json = null;
//        }
//        #endregion


//        #region IEnumerable Methods
//        IEnumerator IEnumerable.GetEnumerator ()
//        {
//            return EnsureCollection ().GetEnumerator ();
//        }
//        #endregion


//        #region IJsonWrapper Methods
//        bool IJsonWrapper.GetBoolean ()
//        {
//            if (type != JsonType.Boolean)
//                throw new InvalidOperationException (
//                    "JsonData instance doesn't hold a boolean");

//            return inst_boolean;
//        }

//        double IJsonWrapper.GetDouble ()
//        {
//            if (type != JsonType.Double)
//                throw new InvalidOperationException (
//                    "JsonData instance doesn't hold a double");

//            return inst_double;
//        }

//        int IJsonWrapper.GetInt ()
//        {
//            if (type != JsonType.Int)
//                throw new InvalidOperationException (
//                    "JsonData instance doesn't hold an int");

//            return inst_int;
//        }

//        long IJsonWrapper.GetLong ()
//        {
//            if (type != JsonType.Long)
//                throw new InvalidOperationException (
//                    "JsonData instance doesn't hold a long");

//            return inst_long;
//        }

//        string IJsonWrapper.GetString ()
//        {
//            if (type != JsonType.String)
//                throw new InvalidOperationException (
//                    "JsonData instance doesn't hold a string");

//            return inst_string;
//        }

//        void IJsonWrapper.SetBoolean (bool val)
//        {
//            type = JsonType.Boolean;
//            inst_boolean = val;
//            json = null;
//        }

//        void IJsonWrapper.SetDouble (double val)
//        {
//            type = JsonType.Double;
//            inst_double = val;
//            json = null;
//        }

//        void IJsonWrapper.SetInt (int val)
//        {
//            type = JsonType.Int;
//            inst_int = val;
//            json = null;
//        }

//        void IJsonWrapper.SetLong (long val)
//        {
//            type = JsonType.Long;
//            inst_long = val;
//            json = null;
//        }

//        void IJsonWrapper.SetString (string val)
//        {
//            type = JsonType.String;
//            inst_string = val;
//            json = null;
//        }

//        string IJsonWrapper.ToJson ()
//        {
//            return ToJson ();
//        }

//        void IJsonWrapper.ToJson (JsonWriter writer)
//        {
//            ToJson (writer);
//        }
//        #endregion


//        #region IList Methods
//        int IList.Add (object value)
//        {
//            return Add (value);
//        }

//        void IList.Clear ()
//        {
//            EnsureList ().Clear ();
//            json = null;
//        }

//        bool IList.Contains (object value)
//        {
//            return EnsureList ().Contains (value);
//        }

//        int IList.IndexOf (object value)
//        {
//            return EnsureList ().IndexOf (value);
//        }

//        void IList.Insert (int index, object value)
//        {
//            EnsureList ().Insert (index, value);
//            json = null;
//        }

//        void IList.Remove (object value)
//        {
//            EnsureList ().Remove (value);
//            json = null;
//        }

//        void IList.RemoveAt (int index)
//        {
//            EnsureList ().RemoveAt (index);
//            json = null;
//        }
//        #endregion


//        #region IOrderedDictionary Methods
//        IDictionaryEnumerator IOrderedDictionary.GetEnumerator ()
//        {
//            EnsureDictionary ();

//            return new OrderedDictionaryEnumerator (
//                object_list.GetEnumerator ());
//        }

//        void IOrderedDictionary.Insert (int idx, object key, object value)
//        {
//            string property = (string) key;
//            JsonData data  = ToJsonData (value);

//            this[property] = data;

//            KeyValuePair<string, JsonData> entry =
//                new KeyValuePair<string, JsonData> (property, data);

//            object_list.Insert (idx, entry);
//        }

//        void IOrderedDictionary.RemoveAt (int idx)
//        {
//            EnsureDictionary ();

//            inst_object.Remove (object_list[idx].Key);
//            object_list.RemoveAt (idx);
//        }
//        #endregion


//        #region Private Methods
//        private ICollection EnsureCollection ()
//        {
//            if (type == JsonType.Array)
//                return (ICollection) inst_array;

//            if (type == JsonType.Object)
//                return (ICollection) inst_object;

//            throw new InvalidOperationException (
//                "The JsonData instance has to be initialized first");
//        }

//        private IDictionary EnsureDictionary ()
//        {
//            if (type == JsonType.Object)
//                return (IDictionary) inst_object;

//            if (type != JsonType.None)
//                throw new InvalidOperationException (
//                    "Instance of JsonData is not a dictionary");

//            type = JsonType.Object;
//            inst_object = new Dictionary<string, JsonData> ();
//            object_list = new List<KeyValuePair<string, JsonData>> ();

//            return (IDictionary) inst_object;
//        }

//        private IList EnsureList ()
//        {
//            if (type == JsonType.Array)
//                return (IList) inst_array;

//            if (type != JsonType.None)
//                throw new InvalidOperationException (
//                    "Instance of JsonData is not a list");

//            type = JsonType.Array;
//            inst_array = new List<JsonData> ();

//            return (IList) inst_array;
//        }

//        private JsonData ToJsonData (object obj)
//        {
//            if (obj == null)
//                return null;

//            if (obj is JsonData)
//                return (JsonData) obj;

//            return new JsonData (obj);
//        }

//        private static void WriteJson (IJsonWrapper obj, JsonWriter writer)
//        {
//            if (obj == null) {
//                writer.Write (null);
//                return;
//            }

//            if (obj.IsString) {
//                writer.Write (obj.GetString ());
//                return;
//            }

//            if (obj.IsBoolean) {
//                writer.Write (obj.GetBoolean ());
//                return;
//            }

//            if (obj.IsDouble) {
//                writer.Write (obj.GetDouble ());
//                return;
//            }

//            if (obj.IsInt) {
//                writer.Write (obj.GetInt ());
//                return;
//            }

//            if (obj.IsLong) {
//                writer.Write (obj.GetLong ());
//                return;
//            }

//            if (obj.IsArray) {
//                writer.WriteArrayStart ();
//                foreach (object elem in (IList) obj)
//                    WriteJson ((JsonData) elem, writer);
//                writer.WriteArrayEnd ();

//                return;
//            }

//            if (obj.IsObject) {
//                writer.WriteObjectStart ();

//                foreach (DictionaryEntry entry in ((IDictionary) obj)) {
//                    writer.WritePropertyName ((string) entry.Key);
//                    WriteJson ((JsonData) entry.Value, writer);
//                }
//                writer.WriteObjectEnd ();

//                return;
//            }
//        }
//        #endregion


//        public int Add (object value)
//        {
//            JsonData data = ToJsonData (value);

//            json = null;

//            return EnsureList ().Add (data);
//        }

//        public void Clear ()
//        {
//            if (IsObject) {
//                ((IDictionary) this).Clear ();
//                return;
//            }

//            if (IsArray) {
//                ((IList) this).Clear ();
//                return;
//            }
//        }

//        public bool Equals (JsonData x)
//        {
//            if (x == null)
//                return false;

//            if (x.type != this.type)
//                return false;

//            switch (this.type) {
//            case JsonType.None:
//                return true;

//            case JsonType.Object:
//                return this.inst_object.Equals (x.inst_object);

//            case JsonType.Array:
//                return this.inst_array.Equals (x.inst_array);

//            case JsonType.String:
//                return this.inst_string.Equals (x.inst_string);

//            case JsonType.Int:
//                return this.inst_int.Equals (x.inst_int);

//            case JsonType.Long:
//                return this.inst_long.Equals (x.inst_long);

//            case JsonType.Double:
//                return this.inst_double.Equals (x.inst_double);

//            case JsonType.Boolean:
//                return this.inst_boolean.Equals (x.inst_boolean);
//            }

//            return false;
//        }

//        public JsonType GetJsonType ()
//        {
//            return type;
//        }

//        public void SetJsonType (JsonType type)
//        {
//            if (this.type == type)
//                return;

//            switch (type) {
//            case JsonType.None:
//                break;

//            case JsonType.Object:
//                inst_object = new Dictionary<string, JsonData> ();
//                object_list = new List<KeyValuePair<string, JsonData>> ();
//                break;

//            case JsonType.Array:
//                inst_array = new List<JsonData> ();
//                break;

//            case JsonType.String:
//                inst_string = default (String);
//                break;

//            case JsonType.Int:
//                inst_int = default (Int32);
//                break;

//            case JsonType.Long:
//                inst_long = default (Int64);
//                break;

//            case JsonType.Double:
//                inst_double = default (Double);
//                break;

//            case JsonType.Boolean:
//                inst_boolean = default (Boolean);
//                break;
//            }

//            this.type = type;
//        }

//        public string ToJson ()
//        {
//            if (json != null)
//                return json;

//            StringWriter sw = new StringWriter ();
//            JsonWriter writer = new JsonWriter (sw);
//            writer.Validate = false;

//            WriteJson (this, writer);
//            json = sw.ToString ();

//            return json;
//        }

//        public void ToJson (JsonWriter writer)
//        {
//            bool old_validate = writer.Validate;

//            writer.Validate = false;

//            WriteJson (this, writer);

//            writer.Validate = old_validate;
//        }

//        public override string ToString ()
//        {
//            switch (type) {
//            case JsonType.Array:
//                return "JsonData array";

//            case JsonType.Boolean:
//                return inst_boolean.ToString ();

//            case JsonType.Double:
//                return inst_double.ToString ();

//            case JsonType.Int:
//                return inst_int.ToString ();

//            case JsonType.Long:
//                return inst_long.ToString ();

//            case JsonType.Object:
//                return "JsonData object";

//            case JsonType.String:
//                return inst_string;
//            }

//            return "Uninitialized JsonData";
//        }
//    }


//    internal class OrderedDictionaryEnumerator : IDictionaryEnumerator
//    {
//        IEnumerator<KeyValuePair<string, JsonData>> list_enumerator;


//        public object Current {
//            get { return Entry; }
//        }

//        public DictionaryEntry Entry {
//            get {
//                KeyValuePair<string, JsonData> curr = list_enumerator.Current;
//                return new DictionaryEntry (curr.Key, curr.Value);
//            }
//        }

//        public object Key {
//            get { return list_enumerator.Current.Key; }
//        }

//        public object Value {
//            get { return list_enumerator.Current.Value; }
//        }


//        public OrderedDictionaryEnumerator (
//            IEnumerator<KeyValuePair<string, JsonData>> enumerator)
//        {
//            list_enumerator = enumerator;
//        }


//        public bool MoveNext ()
//        {
//            return list_enumerator.MoveNext ();
//        }

//        public void Reset ()
//        {
//            list_enumerator.Reset ();
//        }
//    }
//}
